﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace CompiladorV
{
    class Controlador
    {
        Compilador ventana1 = new Compilador();
        Instrucciones ventana2;
        

        public Controlador()
        {
            ventana1.AgregarDatos += new DatosEventHandler(code);            
        }

        public void code(string[] assembler)
        {
            string[] assemblerData = Data(assembler);
            string[] assemblerCode = Code(assembler);

            string[] desifrado = DesifrarCode(assemblerCode, assemblerData);
                       
            ventana2 = new Instrucciones(desifrado);
        }

       
        public void Go()
        {
            Application.Run(ventana1);
        }

        public static string[] Data(string[] palabras)
        {
            int ndata = 0;
            int ncode = 0;


            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("DATA"))
                {
                    ndata = i;
                }
            }

            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("CODE"))
                {
                    ncode = i;
                }
            }

            string[] data = new string[ncode - 1];

            for (int j = 0; j < ncode - 1; j++)
            {

                data[j] = palabras[j + 1];

            }

            return data;
        }



        public static string[] Code(string[] palabras)
        {
            int ndata = 0;
            int ncode = 0;

            string[] data = Data(palabras);

            int b = 0;

            string[] temp = new string[2 * data.Length];

            foreach (string dato in data)
            {

                int n = dato.IndexOf(" ");
                string nombre = dato.Substring(0, n);
                string numero = dato.Substring(n + 1);

                temp[b] = "MOV B," + numero;
                temp[b + 1] = "MOV (" + nombre + "),B";



                b = b + 2;
            }


            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("DATA"))
                {
                    ndata = i;
                }
            }

            for (int i = 0; i < palabras.Length; i++)
            {
                if (palabras[i].Contains("CODE"))
                {
                    ncode = i;
                }
            }

            string[] code = new string[palabras.Length - ncode - 1 + temp.Length];

            for (int j = 0; j < temp.Length; j++)
            {
                code[j] = temp[j];
            }

            int k = data.Length + 2;
            for (int j = temp.Length; j < palabras.Length - ncode + temp.Length -1; j++)
            {

                code[j] = palabras[k];
                k++;
            }

            
            return code;
        }

        public static string[] DesifrarCode(string[] Code, string[] Data)
        {
            /*int m = 0;
            for (int i = 0; i < Code.Length; i++)
            {
                if (Code[i].Contains("JMP"))
                {
                    m++;

                }
                m++;

            }*/
            //string[] Desifrado = new string[Code.Length];
            List<string> Des= new List<string>();
            int j = 0;
            for (int i = 0; i < Code.Length; i++)
            {
                Des.Add(DesifrarInstruccion(Code[i], Data, Code));
               // Desifrado[j] = DesifrarInstruccion(Code[i], Data, Code);
                /*if (Code[i].Contains("JMP"))
                {
                    j++;

                    int c = Code[i].IndexOf(" ");
                    string sub = Code[i].Substring(c + 1);
                    Desifrado[j] = DesifrarInstruccion("JEQ " + sub, Data, Code);



                }*/
                if (Code[i].Contains("RET"))
                {
                    Des.Add("=> \"0000100101000000100000000\",");
                }
                else if (Code[i].Contains("PUSH A"))
                {
                    Des.Add("=> \"0001000000000000000000000\",");
                }
                else if (Code[i].Contains("PUSH B"))
                {
                    Des.Add("=> \"0001000000000000000000000\",");
                }
               
                j++;

            }
            string[] Desifrado = new string[Des.Count];
            for (int i = 0; i < Desifrado.Length; i++)
            {
                Desifrado[i] = Des[i];
            }
            int k = 0;
            for (int i = 0; i < Desifrado.Length; i++)
            {
                if (Desifrado[i].Length != 0)
                {
                    Desifrado[k] = Desifrado[i];
                    k++;
                }
            }

            string[] Desifrado2 = new string[Desifrado.Length + 1];
            for (int i = 0; i < Desifrado.Length;i++ )
            {
                Desifrado2[i + 1] = Desifrado[i];
            }
            Desifrado2[0]="=> \"0001000000000000000000000\",";


            string[] Desifrado1 = new string[k+1];
            for (int i = 0; i < k+1; i++)
            {

                Desifrado1[i] = Convert.ToString(i) + Desifrado2[i];


            }

            string[] completo = new string[16];
            if (Desifrado1.Length < 16)
            {
               

                for (int i = 0; i < Desifrado1.Length; i++)
                {
                    completo[i] = Desifrado1[i];
                }

                for (int i = Desifrado1.Length; i < completo.Length; i++)
                {
                    completo[i] = i + "=> \"0000000000000000000000000\",";
                     
                }
            }

            completo[15] = completo[15].Substring(0, completo[15].Length - 1);


            return completo;
        }


        public static string DesifrarInstruccion(string instruccion, string[] Data, string[] Code)
        {
            string ins = instruccion;
            string señalControl = "";
            if (instruccion.Contains("MOV"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000001000101000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000001010010000000000";

                }
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001001100101000000000";
                }
                else if (instruccion.Contains("B,(B)"))
                {
                    señalControl += "0000001001100110000000000";

                }
                else if (instruccion.Contains("(B),A"))
                {
                    señalControl += "0000001011010001000000000";
                }

                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000011001010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }

                else if (instruccion.Contains("B,("))
                {
                    señalControl += "00000000011001100" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }

                else if (instruccion.Contains("),A"))
                {
                    señalControl += "00000000110100000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }

                else if (instruccion.Contains("),B"))
                {
                    señalControl += "00000000110001000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000011101010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }

                else if (instruccion.Contains("B,"))
                {
                    señalControl += "00000000011101100" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));

                }

            }
            else if (instruccion.Contains("ADD"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000001000001000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000001000010000000000";

                }
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001001100010000000000";
                }
                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000011000010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000011100010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
                else if (instruccion.Contains("A ( "))
                {
                    señalControl += "00000000110000000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }


            }
            else if (instruccion.Contains("SUB"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000000000001000000000";

                }
                else if (instruccion.Contains("B,A"))
                {
                    señalControl += "0000000000000010000000000";

                }
                else if (instruccion.Contains("A,(B)"))
                {
                    señalControl += "0000001000100001000000000";
                }
                else if (instruccion.Contains("A,("))
                {
                    señalControl += "00000000001000010" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000001100010" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
                else if (instruccion.Contains("A ( "))
                {
                    señalControl += "00000000100000000" + EntregarDir(instruccion.Substring(instruccion.IndexOf("(") + 1, instruccion.Substring(instruccion.IndexOf("(") + 1).Length - instruccion.Substring(instruccion.IndexOf(")"), instruccion.Substring(instruccion.IndexOf(")")).Length).Length), Data);
                }
            }
            else if (instruccion.Contains("INC"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0000000001110001000000001";

                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0000000001001010000000000";

                }
            }
            else if (instruccion.Contains("DEC A"))
            {
                señalControl += "0000000000110001000000001";
            }
            else if (instruccion.Contains("JMP"))
            {
                señalControl += "00000000010000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JMP") + 4), Code);
            }
            else if (instruccion.Contains("JEQ"))
            {
                señalControl += "00000000000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JEQ") + 4), Code);
            }
            else if (instruccion.Contains("JNE"))
            {
                señalControl += "00000100000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JNE") + 4), Code);
            }
            else if (instruccion.Contains("CMP"))
            {
                if (instruccion.Contains("A,B"))
                {
                    señalControl += "0000000000000000000000000";
                }
                else if (instruccion.Contains("A,"))
                {
                    señalControl += "00000000001100000" + EntregarLiteral(instruccion.Substring(instruccion.IndexOf(",") + 1));
                }
            }

            else if (instruccion.Contains("JGT"))
            {
                señalControl += "10000000000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JGT") + 4), Code);
            }


            else if (instruccion.Contains("JGE"))
            {
                señalControl += "10000000000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JGE") + 4), Code);
            }

            else if (instruccion.Contains("JLE"))
            {
                señalControl += "10000100000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JLE") + 4), Code);
            }


            else if (instruccion.Contains("JLT"))
            {
                señalControl += "10000100000000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("JLT") + 4), Code);
            }
            else if (instruccion.Contains("CALL"))
            {
                señalControl += "01010001110000001" + EntregarLabel(instruccion.Substring(instruccion.IndexOf("CALL") + 5), Code);
            }
            else if (instruccion.Contains("RET"))
            {
                señalControl += "0010000000000000000000000";
            }
            else if (instruccion.Contains("PUCH"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0000000111010000000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0000000111000100000000000";
                }

            }
            else if (instruccion.Contains("POP"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0001011101000000000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0001011101000000000000000";
                }

            }
            /***********************************************************/
            else if (instruccion.Contains("IN"))
            {
                if (instruccion.Contains("A"))
                {
                    señalControl += "0000000001011101000000000";
                }
                else if (instruccion.Contains("B"))
                {
                    señalControl += "0000000001011110000000000";
                }

            }
            else
            {
                return señalControl;
            }
            return "=> \"" + señalControl + "\",";


        }
        public static string EntregarLiteral(string instruccion)
        {
            if (instruccion.Contains("b"))
            {
                instruccion = instruccion.Substring(0, instruccion.Length - instruccion.Substring(instruccion.IndexOf("b")).Length);
                if (instruccion.Length < 8)
                {
                    for (int k = 0; instruccion.Length < 8; k++)
                    {
                        instruccion = "0" + instruccion;
                    }
                }

            }

            else if (instruccion.Contains("h"))
            {
                instruccion = instruccion.Substring(0, instruccion.Length - instruccion.Substring(instruccion.IndexOf("h")).Length);
                instruccion = decOrHexToBin(instruccion, 1);
            }
            else
            {
                instruccion = decOrHexToBin(instruccion, 0);

            }



            return instruccion;
        }
        public static string EntregarDir(string instruccion, string[] Data)
        {

            string aux = "";
            for (int i = 0; i < Data.Length; i++)
            {
                if (Data[i].Contains(instruccion))
                {
                    aux = Data[i];
                    aux = aux.Remove(0, instruccion.Length);
                    aux = decOrHexToBin(Convert.ToString(i), 0);
                    return aux;
                }

            }


            return aux;
        }
        public static string EntregarLabel(string instruccion, string[] Code)
        {
            string dirLabel = "";

            int c = 0;
            int j = 0;
            int k = 0;

            for (int i = 0; i < Code.Length; i++)
            {
                if (Code[i].Contains(instruccion + ":"))
                {
                    dirLabel = Code[i];
                    
                    dirLabel = decOrHexToBin(Convert.ToString(i-c+1+k), 0);
                    return dirLabel;
                }

                if (Code[i].Contains(":"))
                {
                    c++;
                }

                if (Code[i].Contains("POP") || Code[i].Contains("PUSH") || Code[i].Contains("RET"))
                {
                    k++;
                }

            }

            return dirLabel;
        }
        public static string decOrHexToBin(string numS, int mode)
        {
            //mode 0 es de decimal, mode 1 es de hexadecimal
            string inBinary = "";
            int numI;
            string aux = "";
            if (mode == 0)
            {
                Int32.TryParse(numS, out numI);
                aux = Convert.ToString((sbyte)numI, 2);
            }
            else
            {
                numI = Int32.Parse(numS, System.Globalization.NumberStyles.HexNumber);
                aux = Convert.ToString((sbyte)numI, 2);
            }
            //retornamos 0 si el numero lo es
            if (numI == 0)
            {
                inBinary = "00000000";
            }
            //convertidoms a sByte, con signo y luego completamos los 0 para que sean 8 bits
            else if (numI > 0)
            {
                if (aux.Length > 8)
                {
                    inBinary = aux.Substring(8, 8);
                }
                else
                {
                    while (aux.Length < 8)
                    {
                        aux = "0" + aux;
                    }
                    inBinary = aux;
                }
            }
            //convertimos a Sbyte, con signo y luego truncamos para que sean solo 8 bits o agregamos cero si es de menos
            else
            {
                if (aux.Length > 8)
                {
                    inBinary = aux.Substring(8, 8);
                }
                else
                {
                    while (aux.Length < 8)
                    {
                        aux = "1" + aux;
                    }
                }
            }
            return inBinary;
        }

       

    }
        
    public delegate void DatosEventHandler (string[]datos);

}
